#ifndef __UTIL__COLOUR_HPP__
#define __UTIL__COLOUR_HPP__

#include <util/point.hpp>
#include <util/constrained_value.hpp>

namespace util {
  /** @brief A utility class to encapsulate colour data.

      Each colour component is kept clamped to a range of zero to one.
      If a value of a component is above one or below zero by the
      result of any operation, the value is clamped.
  */
  class colour {
  public:
    colour(double r = 0.0, double g = 0.0, double b = 0.0, double a = 1.0);
    colour(const colour& c);

    void set(double r = 0.0, double g = 0.0, double b = 0.0, double a = 1.0);
    void r(double r);
    void g(double g);
    void b(double b);
    void a(double a);

    double r() const;
    double g() const;
    double b() const;
    double a() const;

    const double* c_data() const;

    colour& operator= (const colour& c);
    colour& operator+=(const colour& c);
    colour& operator-=(const colour& c);
    colour& operator*=(double s);
    colour& operator/=(double s);

  private:
    d01 data[4];
  };

  colour blend(const colour& a, const colour& b, double w); 
  colour fromHSV(double h, double s, double v);
}

util::colour operator+(const util::colour& a, const util::colour& b);
util::colour operator-(const util::colour& a, const util::colour& b);
util::colour operator*(double s, const util::colour& c);
util::colour operator*(const util::colour& c, double s);
util::colour operator/(double s, const util::colour& c);
util::colour operator/(const util::colour& c, double s);

bool operator==(const util::colour& a, const util::colour& b);
bool operator!=(const util::colour& a, const util::colour& b);

std::ostream& operator<<(std::ostream& os, const util::colour& c);
std::istream& operator>>(std::istream& is, util::colour& c);

#endif
